package tests;

import static org.junit.Assert.*;

import items.Battery;
import items.RepairKit;

import java.util.Iterator;
import java.util.NoSuchElementException;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import condition.*;

import elements.Element;
import elements.Robot;
import elements.Wall;
import exceptions.IllegalPlacementException;
import gui.Facade;
import roborally.EnergyAmount;
import roborally.EnergyUnit;
import roborally.Orientation;
import roborally.Board;
import roborally.Position;


/**
 * @version	3.0
 * @author 	Lies Tambeur 	r0264469	2Bcwsbbh
 * @author	Eline Vanrykel	r0264543	2Bcwselt
 * 
 */
public class BoardTest {
	
	/**
	 * Set up an immutable test fixture.
	 * @post   
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		
	}
	
	//private velden
	private Facade facade;
	private Board board20001000With1Wall1Robot1Battery;
	private Robot robotb1 = new Robot();
	private Wall wallb1 = new Wall();
	private Battery batteryb1 = new Battery(new EnergyAmount(1000,EnergyUnit.WATTSECONDS),500);
	private Board board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition;
	private Robot robotb2 = new Robot(Orientation.UP,new EnergyAmount(3000,EnergyUnit.WATTSECONDS));
	private Wall wall1b2 = new Wall();
	private Wall wall2b2 = new Wall();
	private Battery batteryb2 = new Battery(new EnergyAmount(2000, EnergyUnit.WATTSECONDS),1500);
	private Battery battery2b2 = new Battery(new EnergyAmount(500,EnergyUnit.WATTSECONDS),150);
	private Board emptyBoard350500 = new Board(350,500);
	private EnergyAmount zeroEnergy = new EnergyAmount();

	

	/**
	 * Set up a mutable test fixture.
	 * 
	 * @post   The variable robot33Orient0Energy20000 references a new
	 *         robot with with position (3,3), energy 20000 and orientation 0.
	 * @post   The variable robot82Orient3Energy8000 references a new
	 *         robot with  position (8,2), energy 8000 and orientation 3.
	 */
	@Before
	public void setUp() throws Exception {
		facade = new Facade();
		board20001000With1Wall1Robot1Battery = new Board(2000, 1000);
		board20001000With1Wall1Robot1Battery.putElement(new Position(3,3), robotb1);
		board20001000With1Wall1Robot1Battery.putElement(new Position(3,4), wallb1);
		board20001000With1Wall1Robot1Battery.putElement(new Position(1,2), batteryb1);
		facade.addBoard(board20001000With1Wall1Robot1Battery);
		
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition = new Board(100,500);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(new Position(5,4), robotb2);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(new Position(6,7), wall1b2);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(new Position(6,8), wall2b2);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(new Position(5,4), batteryb2);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(new Position(11,3), battery2b2);
		facade.addBoard(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition);
	}
	
	@Test
	public final void extendedconstructor_Normal() { 
		Board board = new Board(500, 1000);
		assertEquals(500, board.getWidth());
		assertEquals(1000, board.getHeight());
	}
	
	@Test
	public final void getWalls_1Wall(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.<Wall>getElementsOfType(Wall.class).size());
		Iterator<Wall> it = board20001000With1Wall1Robot1Battery.<Wall>getElementsOfType(Wall.class).iterator();
		while(it.hasNext()){
			Wall wall = it.next();
			assertNotNull(wall);
			assertEquals(3, wall.getPosition().getX());
			assertEquals(4, wall.getPosition().getY());
		}
	}
	
	@Test
	public final void isValidPosition_NoElement_TrueCase(){
		assertTrue(board20001000With1Wall1Robot1Battery.isValidPosition(new Position(1,1),new Battery(zeroEnergy,0)));
	}
	
	@Test
	public final void isValidPosition_NoElement_FalseCase(){
		assertFalse(board20001000With1Wall1Robot1Battery.isValidPosition(new Position(5000,5000),new Battery(zeroEnergy,0)));
	}
	
	@Test
	public final void isValidPosition_WallPosition(){
		assertFalse(board20001000With1Wall1Robot1Battery.isValidPosition(new Position(3,4),new Battery(zeroEnergy,0)));
	}
	
	@Test
	public final void isValidPosition_RobotPosition(){
		assertTrue(board20001000With1Wall1Robot1Battery.isValidPosition(new Position(3,3),new Battery(zeroEnergy,0)));
	}
	
	@Test
	public final void isValidPosition_BatteryPosition(){
		assertTrue(board20001000With1Wall1Robot1Battery.isValidPosition(new Position(1,2),new Battery(zeroEnergy,0)));
	}
	
	@Test
	public final void getAllElements(){
		assertEquals(3, board20001000With1Wall1Robot1Battery.getAllElements().size());
		assertTrue(board20001000With1Wall1Robot1Battery.getAllElements().contains(robotb1));
		assertTrue(board20001000With1Wall1Robot1Battery.getAllElements().contains(wallb1));
		assertTrue(board20001000With1Wall1Robot1Battery.getAllElements().contains(batteryb1));
	}
	
	@Test
	public final void getElementsPosition_1Element(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.getElements(new Position(3,3)).size());
		assertTrue(board20001000With1Wall1Robot1Battery.getElements(new Position(3,3)).contains(robotb1));
	}
	
	@Test
	public final void getElementsPosition_NoElements(){
		assertEquals(0, board20001000With1Wall1Robot1Battery.getElements(new Position(10,10)).size());
	}
	
	@Test
	public final void getElementsPosition_MultipleElements(){
		assertEquals(2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).size());
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).contains(batteryb2));
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).contains(robotb2));
	}
	
	@Test
	public final void getItemsPosition_NoItems(){
		assertEquals(0, board20001000With1Wall1Robot1Battery.getItems(new Position(3,3)).size());
	}
	
	@Test
	public final void getItemsPosition_OneItem(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.getItems(new Position(1,2)).size());
		assertTrue(board20001000With1Wall1Robot1Battery.getElements(new Position(1,2)).contains(batteryb1));
	}
	
	@Test
	public final void getItemsPosition_OneItemMoreElements(){
		assertEquals(1, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getItems(new Position(5, 4)).size());
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).contains(batteryb2));
	}
	
	@Test
	public final void getFirstElementStartingAt_Case1Hit(){
		assertEquals(board20001000With1Wall1Robot1Battery.<Wall>getElementsOfType(Wall.class).iterator().next(),board20001000With1Wall1Robot1Battery.getFirstElementStartingAt(new Position(10,4), Orientation.LEFT));
	}
	
	@Test
	public final void getFirstElementsStartingAt_CaseNoHit(){
		assertEquals(null,board20001000With1Wall1Robot1Battery.getFirstElementStartingAt(new Position(10,50), Orientation.LEFT));
	}
	
	@Test
	public final void getFirstElementsStartingAt_CaseMultipleHits(){
		assertTrue( (batteryb2 == board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getFirstElementStartingAt(new Position(50,4), Orientation.LEFT))
				|| (robotb2 == board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getFirstElementStartingAt(new Position(50,4), Orientation.LEFT)));
	}
	
	@Test
	public final void getFirstElementsStartingAt_OrientationUP_1Hit(){
		assertEquals(wall2b2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getFirstElementStartingAt(new Position(6,100), Orientation.UP));
	}
	
	@Test
	public final void getFirstElementsStartingAt_OrientationRIGHT_1Hit(){
		assertEquals(wallb1, board20001000With1Wall1Robot1Battery.getFirstElementStartingAt(new Position(0,4), Orientation.RIGHT));
	}
	
	@Test
	public final void getFirstElementsStartingAt_OrientationDOWN_1Hit(){
		assertEquals(wall1b2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getFirstElementStartingAt(new Position(6,0), Orientation.DOWN));
	}
	
	@Test
	public final void getFirstElementsStartingAt_OrientationLEFT_1Hit(){
		assertEquals(battery2b2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getFirstElementStartingAt(new Position(50,3), Orientation.LEFT));

	}
	
	@Test
	public final void getMaxHeight(){
		assertEquals(Long.MAX_VALUE, Board.getMaxHeight());
	}
	
	@Test
	public final void getHeight(){
		assertEquals(1000, board20001000With1Wall1Robot1Battery.getHeight());
	}
	
	@Test
	public final void getWidth(){
		assertEquals(2000, board20001000With1Wall1Robot1Battery.getWidth());
	}
	
	@Test
	public final void getRobots_1RobotOnBoard(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.<Robot>getElementsOfType(Robot.class).size());
		assertTrue(board20001000With1Wall1Robot1Battery.<Robot>getElementsOfType(Robot.class).contains(robotb1));
	}
	
	@Test
	public final void getRobots_NoRobotsOnBoard(){
		assertEquals(0, emptyBoard350500.<Robot>getElementsOfType(Robot.class).size());
	}
	
	@Test
	public final void getWalls_1WallOnBoard(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.<Wall>getElementsOfType(Wall.class).size());
		assertTrue(board20001000With1Wall1Robot1Battery.<Wall>getElementsOfType(Wall.class).contains(wallb1));
	}
	
	@Test
	public final void getWalls_MultipleWallOnBoard(){
		assertEquals(2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Wall>getElementsOfType(Wall.class).size());
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Wall>getElementsOfType(Wall.class).contains(wall1b2));
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Wall>getElementsOfType(Wall.class).contains(wall2b2));
	}
	
	@Test
	public final void getWalls_NoWallsOnBoard(){
		assertEquals(0, emptyBoard350500.<Wall>getElementsOfType(Wall.class).size());
	}
	
	@Test
	public final void getBatteries_1BatteryOnBoard(){
		assertEquals(1, board20001000With1Wall1Robot1Battery.<Battery>getElementsOfType(Battery.class).size());
		assertTrue(board20001000With1Wall1Robot1Battery.<Battery>getElementsOfType(Battery.class).contains(batteryb1));
	}
	
	@Test
	public final void getBatteries_MultipleBatteriesOnBoard(){
		assertEquals(2, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Battery>getElementsOfType(Battery.class).size());
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Battery>getElementsOfType(Battery.class).contains(batteryb2));
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.<Battery>getElementsOfType(Battery.class).contains(battery2b2));
	}
	
	@Test
	public final void getBatteries_NoBatteriesOnBoard(){
		assertEquals(0, emptyBoard350500.<Battery>getElementsOfType(Battery.class).size());
	}
	
	@Test
	public final void putElement_LegalCase_NoOverlap(){
		Wall theWall = new Wall();
		Position thePosition = new Position(100,400);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(thePosition, theWall);
		assertEquals(theWall, board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(thePosition).iterator().next());
	}
	
	@Test
	public final void putElement_IllegalCase_Overlap(){
		Wall theWall = new Wall();
		Position thePosition = new Position(5,4);
		try{
			board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(thePosition, theWall);
		} catch(IllegalPlacementException e){
			assertTrue(true);
		}
		
	}
	
	@Test
	public final void putElement_OutOfBoard(){
		Wall theWall = new Wall();
		Position thePosition = new Position(100,600);
		try{
			board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(thePosition, theWall);
		} catch(IllegalPlacementException e){
			assertTrue(true);
		}
	}
	
	@Test
	public final void putElement_LegalCase_Overlap(){
		Battery theBattery = new Battery(zeroEnergy,0);
		Position thePosition = new Position(5,4);
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.putElement(thePosition, theBattery);
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(thePosition).contains(theBattery));
	}
	
	@Test
	public final void removeElement_1ElementOnPosition_ElementOnBoard(){
		board20001000With1Wall1Robot1Battery.removeElement(batteryb1);
		assertEquals(board20001000With1Wall1Robot1Battery.getAllElements().size(), 2);
		assertFalse(board20001000With1Wall1Robot1Battery.getElements(new Position(1,2)).contains(batteryb1));
	}
	
	@Test
	public final void removeElement_MultipleElementsOnPosition_ElementOnBoard(){
		board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.removeElement(robotb2);
		assertEquals(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getAllElements().size(), 4);
		assertFalse(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).contains(robotb2));
		assertTrue(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.getElements(new Position(5,4)).contains(batteryb2));
	}
	
	@Test
	public final void removeElement_ElementNotOnBoard(){
		try{
			board20001000With1Wall1Robot1Battery.removeElement(batteryb2);
		} catch (IllegalStateException e) {
			assertTrue(true);
		}
		assertEquals(board20001000With1Wall1Robot1Battery.getAllElements().size(),3);
	}
	
	@Test
	public final void merge_AllElementsAllowed_Overlap(){
		Battery battery1 = new Battery(zeroEnergy,0);
		Wall wall1 = new Wall();
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(3,EnergyUnit.WATTSECONDS));
		Board board1 = new Board(5,5);
		board1.putElement(new Position(2,3),battery1);
		board1.putElement(new Position(5,5), wall1);
		Board board2 = new Board(6,6);
		board2.putElement(new Position(2,3), robot1);
		board1.merge(board2);
		assertEquals(5, board1.getWidth());
		assertEquals(5, board1.getHeight());
		assertTrue(board2.isTerminated());
		assertFalse(board1.isTerminated());
		assertTrue(board1.getElements(new Position(2,3)).contains(battery1));
		assertTrue(board1.getElements(new Position(2,3)).contains(robot1));
		assertTrue(board1.getElements(new Position(5,5)).contains(wall1));
		assertEquals(board1.getAllElements().size(), 3);
	}
	
	@Test
	public final void merge_NotAllElementsAllowed_NoOverlap(){
		Battery battery1 = new Battery(zeroEnergy,0);
		Wall wall1 = new Wall();
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(3,EnergyUnit.WATTSECONDS));
		Board board1 = new Board(5,5);
		board1.putElement(new Position(2,3),battery1);
		board1.putElement(new Position(5,5), wall1);
		Board board2 = new Board(6,6);
		board2.putElement(new Position(6,6), robot1);
		board1.merge(board2);
		assertEquals(5, board1.getWidth());
		assertEquals(5, board1.getHeight());
		assertTrue(board2.isTerminated());
		assertFalse(board1.isTerminated());
		assertTrue(board1.getElements(new Position(2,3)).contains(battery1));
		assertTrue(board1.getElements(new Position(5,5)).contains(wall1));
		assertTrue(robot1.isTerminated());
		assertNull(robot1.getBoard());
		assertEquals(board1.getAllElements().size(), 2);
	}
	
	@Test
	public final void merge_NullBoard(){
		try{
			board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.merge(null);
		} catch(NullPointerException e){
			assertTrue(true);
		}
		
	}
	
	@Test 
	public final void terminate(){
		Battery battery1 = new Battery(zeroEnergy,0);
		Wall wall1 = new Wall();
		Board board1 = new Board(5,5);
		board1.putElement(new Position(2,3),battery1);
		board1.putElement(new Position(5,5), wall1);
		board1.terminate();
		assertTrue(battery1.isTerminated());
		assertTrue(wall1.isTerminated());
		assertTrue(board1.isTerminated());
		assertNull(battery1.getBoard());
		assertNull(wall1.getBoard());
	}
	
	@Test
	public final void getAllPositionsInUse(){
		assertTrue(board20001000With1Wall1Robot1Battery.getAllPositionsInUse().contains(new Position(3,3)));
		assertTrue(board20001000With1Wall1Robot1Battery.getAllPositionsInUse().contains(new Position(3,4)));
		assertTrue(board20001000With1Wall1Robot1Battery.getAllPositionsInUse().contains(new Position(1,2)));
		assertEquals(board20001000With1Wall1Robot1Battery.getAllPositionsInUse().size(),3);
	} 
	
	@Test
	public final void isPositionOnBoard_TrueCase(){
		assertTrue(board20001000With1Wall1Robot1Battery.isPositionOnBoard(new Position(5,5)));
	}
	
	@Test
	public final void isPositionOnBoard_FalseCaseX(){
		assertFalse(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.isPositionOnBoard(new Position(101,5)));
	}
	
	@Test
	public final void isPositionOnBoard_FalseCaseY(){
		assertFalse(board100500With2Walls1BatteryAnd1Robot1BatteryOnSamePosition.isPositionOnBoard(new Position(1,505)));
	}
	
	@Test
	public final void getElementsCondition_2MeetCondition(){ 
		Condition condition = new Or(new EnergyAtLeast(new EnergyAmount(100,EnergyUnit.WATTSECONDS)), new WallCondition());
		Board board = new Board(100, 200);
		facade.addBoard(board);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(1,EnergyUnit.KILOJOULE));
		Battery battery1 = new Battery(new EnergyAmount(), 500);
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(1,2), robot1);
		board.putElement(new Position(3,4), new Wall());
		board.putElement(new Position(3,3), battery1);
		board.putElement(new Position(3,3), robot2);
		Iterator<Element> it = board.getElements(condition);
		assertTrue(it.hasNext());
		Element el = it.next();
		assertTrue(el.equals(robot1) || el.equals(robot2));
		assertTrue(it.hasNext());
		Element el2 = it.next();
		assertTrue(el2.equals(robot1) || el2.equals(robot2));
		assertFalse(it.hasNext());
		board.terminate();
	}
	
	@Test
	public final void getElementsCondition_NoneMeetCondition(){
		Condition condition = new Or(new EnergyAtLeast(new EnergyAmount(100,EnergyUnit.WATTSECONDS)), new WallCondition());
		Board board = new Board(100, 200);
		facade.addBoard(board);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(0.001,EnergyUnit.KILOJOULE));
		Battery battery1 = new Battery(new EnergyAmount(), 500);
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(1,2), robot1);
		board.putElement(new Position(3,4), new Wall());
		board.putElement(new Position(3,3), battery1);
		board.putElement(new Position(3,5), robot2);
		Iterator<Element> it = board.getElements(condition);
		assertFalse(it.hasNext());
		board.terminate();
	}
	
	@Test
	public final void getElementsCondition_RobotMeetsCondition(){
		Condition condition = new AtItem();
		Board board = new Board(100, 200);
		facade.addBoard(board);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(5,EnergyUnit.WATTSECONDS));
		Battery battery1 = new Battery(new EnergyAmount(), 500);
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(1,2), robot1);
		board.putElement(new Position(1,2), battery1);
		board.putElement(new Position(3,5), robot2);
		Iterator<Element> it = board.getElements(condition);
		assertTrue(it.hasNext());
		assertEquals(robot1, it.next());
		assertFalse(it.hasNext());
		board.terminate();
	}
	
	@Test
	public final void getElementsCondition_Items(){
		Condition condition = new EnergyAtLeast(new EnergyAmount(10,EnergyUnit.WATTSECONDS));
		Board board = new Board(100, 200);
		facade.addBoard(board);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(50,EnergyUnit.WATTSECONDS));
		Battery battery1 = new Battery(new EnergyAmount(500,EnergyUnit.JOULE), 500);
		RepairKit rep1 = new RepairKit(400, new EnergyAmount(1,EnergyUnit.KILOJOULE));
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(1,2), robot1);
		board.putElement(new Position(1,2), battery1);
		board.putElement(new Position(3,5), rep1);
		board.putElement(new Position(10,11), robot2);
		
		Iterator<Element> it = board.getElements(condition);
		assertTrue(it.hasNext());
		Element el = it.next();
		assertTrue(el.equals(robot1) || el.equals(battery1) || el.equals(rep1));
		assertTrue(it.hasNext());
		Element el2 = it.next();
		assertTrue(el2.equals(robot1) || el2.equals(battery1) || el2.equals(rep1));
		assertTrue(it.hasNext());
		Element el3 = it.next();
		assertTrue(el3.equals(robot1) || el3.equals(battery1) || el3.equals(rep1));
		assertFalse(it.hasNext());
		try{
			it.next();
		}
		catch(NoSuchElementException e){
			assertTrue(true);
		}
		board.terminate();
	}
	
	@Test
	public final void getElementsCondition_InvalidCondition(){
		Condition condition = null;
		Board board = new Board(100, 200);
		facade.addBoard(board);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(50,EnergyUnit.WATTSECONDS));
		Battery battery1 = new Battery(new EnergyAmount(500,EnergyUnit.JOULE), 500);
		RepairKit rep1 = new RepairKit(400, new EnergyAmount(1,EnergyUnit.KILOJOULE));
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(1,2), robot1);
		board.putElement(new Position(1,2), battery1);
		board.putElement(new Position(3,5), rep1);
		board.putElement(new Position(10,11), robot2);
		
		Iterator<Element> it = board.getElements(condition);
		try{
			it.hasNext();
			assertFalse(true);
		}
		catch(IllegalArgumentException e){
			assertTrue(true);
		}
		board.terminate();
	}
	
	
	@Test
	public final void getElementsCondition_SubRangeCondition(){
		Condition condition = new SubRange(new Position(3,2), new Position(4,3));
		Board board = new Board(100, 200);
		Board board2 = new Board(300,100);
		facade.addBoard(board);
		facade.addBoard(board2);
		Robot robot1 = new Robot(Orientation.UP,new EnergyAmount(50,EnergyUnit.WATTSECONDS));
		Battery battery1 = new Battery(new EnergyAmount(500,EnergyUnit.JOULE), 500);
		RepairKit rep1 = new RepairKit(400, new EnergyAmount(1,EnergyUnit.KILOJOULE));
		Robot robot2 = new Robot(Orientation.RIGHT,new EnergyAmount());
		board.putElement(new Position(3,3), robot1);
		board.putElement(new Position(4,2), battery1);
		board.putElement(new Position(3,5), rep1);
		board2.putElement(new Position(4,2), robot2);
		
		Iterator<Element> it = board.getElements(condition);
		assertTrue(it.hasNext());
		Element elem1 = it.next();
		assertTrue(elem1.equals(robot1) || elem1.equals(battery1));
		assertTrue(it.hasNext());
		Element elem2 = it.next();
		assertTrue(elem2.equals(robot1) || elem2.equals(battery1));
		assertFalse(it.hasNext());
		
		board.terminate();
		board2.terminate();
	}
	
	@Test
	public final void putElement_OneElementOnTwoDifferentBoards(){
		Board board1 = new Board(100, 200);
		Board board2 = new Board(1000,3);
		facade.addBoard(board1);
		facade.addBoard(board2);
		Robot robot1 = new Robot();
		board1.putElement(new Position(2,2), robot1);
		try{
			board2.putElement(new Position(0,0), robot1);
			assertTrue(false);
		}
		catch (IllegalStateException e) {
			assertTrue(true);
		}
		board1.terminate();
		board2.terminate();
	}
	
	}